/*
 * Copyright 2011 The Rusted Roof, LLC.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.proteusframework.api.base;

import org.proteusframework.api.config.ConfigProperty;
import org.proteusframework.api.config.IConfigProperty;
import org.proteusframework.api.config.IConfigPropertyPrototype;
import org.proteusframework.api.config.IConfigurable;
import org.proteusframework.api.model.IDisplayableName;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 * Base class for all {@link org.proteusframework.api.config.IConfigurable} named objects.
 *
 * @author Tacoma Four
 */
public abstract class AbstractConfigurable extends AbstractNamedObject implements IConfigurable
{
    private static final Logger logger = Logger.getLogger(AbstractConfigurable.class.getCanonicalName());

    /**
     * Collection of runtime-defined configuration properties.
     */
    protected Map<String, IConfigProperty> definedProperties = new HashMap<String, IConfigProperty>();

    /**
     * Constructs an abstract configurable object associated with the immutable <code>IDisplayableName</code>.
     *
     * @param displayableName Displayable name
     */
    public AbstractConfigurable(IDisplayableName displayableName)
    {
        super(displayableName);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setConfigProperty(IConfigPropertyPrototype prototype, Object assignedValue)
    {
        ConfigProperty property = new ConfigProperty(prototype, assignedValue);
        definedProperties.put(prototype.getKey(), property);

        onConfigurationPropertySet(property);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void processRawProperty(IConfigProperty property)
    {
        onRawConfigurationPropertySet(property);
    }

    /**
     * Event that provides notice that an internal property was defined at runtime. This event gives the implementor
     * the opportunity to inspect and respond to the newly defined runtime configuration property.
     *
     * @param property property defined
     */
    protected void onConfigurationPropertySet(IConfigProperty property)
    {

    }

    /**
     * Event that provides notice that an internal property was defined at runtime from an XML configuration. This event
     * gives the implementor the opportunity to inspect and respond to the newly defined runtime configuration property
     * by properly parsing and converting it, as applicable, to the correct type of object.
     *
     * @param property property defined
     */
    protected void onRawConfigurationPropertySet(IConfigProperty property)
    {

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IConfigProperty getConfigProperty(String key)
    {
        return definedProperties.get(key);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<IConfigProperty> configuredProperties()
    {
        return definedProperties.values();
    }
}
